/* 
    1.window立即执行函数
    2.创建一个promise构造函数,参数为执行器excutor
        a.
    3.原型方法:
        then方法.返回一个新promise
        分两种情况回调参数为上个promise成功状态resolve(value)调用的参数和失败状态reject(reason)调用的参数
        1.返回的是一个promise对象 => 得到值并改变其成功或失败的状态
        2.返回的是非promise对象 =>  得到值并返回一个成功状态
        3.抛出一个错误 => try---catch 变为失败状态
        4.原型catch方法捕获then里面失败状态
        5.原型finally方法
    4.静态方法
        
        */

// 用一个window执行函数
((window) => {

    // 自定义promise状态值常量
    const PENDING = 'pending'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'



    // 创建一个promise构造函数
    function Promise(excutor) {
        //创建promise默认状态
        this.state = PENDING,
            //创建promise状态的结果
            this.data = undefined,
            //创建promise保存待处理回调的数组
            this.callbacks = [];



        // 将promise的this赋给self,存储起来
        const self = this;



        // resolve(value)状态为FULFILLED,将value保存在data中
        function resolve(value) {
            //只有promise为pending默认状态下才能向下进行
            if (self.state !== PENDING) return


            //将promise改为成功状态
            self.state = FULFILLED
            //将promise成功的value 存到data中
            self.data = value

            //当执行异步回调时,没办法用微任务添加回调 => 只能用宏任务 setTimeout
            if(self.callbacks.length>0){
            setTimeout(() => {
                self.callbacks.forEach(callbackObj => callbackObj.resolve(value))
            }, 0);
            }
        }

        // reject(reason)状态为REJEXTED,将reason保存在data中
        function reject(reason) {
            //只有默认状态下才能向下执行
            if (self.state !== PENDING) return
            // 将promise变为失败状态
            self.state = REJECTED
            // 将promise失败的reason 存到data中
            self.data = reason

            //当执行异步回调时,没办法用微任务添加回调 => 只能用宏任务 setTimeout
            if(self.callbacks.length > 0){
            setTimeout(() => {
                self.callbacks.forEach(callbackObj => callbackObj.reject(reason))
            }, 0);
        }
        }
        //在执行promise中,会同步调用resolve成功和reject失败
        try {
            //promise构造函数执行器excutor包含resolve和reject
            excutor(resolve, reject)

        } catch (error) { // 捕获失败状态reject,reason值为error
            reject(error)
        }
    
    }

        //then原型方法 指定onResolved成功和onRejected失败回调 , 返回一个新的promise对象
        //  1.返回的是一个promise对象 => 得到值并改变其成功或失败的状态
        //  2.返回的是非promise对象 =>  得到值并返回一个成功状态
        //  3.抛出一个错误 => try---catch 变为失败状态


        // promise原型then方法 : 参数为onResolved(成功)和onRejected(失败)
        Promise.prototype.then = function (onResolved, onRejected) {
            //将this存储在self
            const self = this


            // 值穿透 如果onResolved不是函数,指定默认函数,value向下传递
            onResolved = typeof onResolved === 'function' ? onResolved : value => value
            // 如果onRejected不是函数,指定默认函数,reason 向下传递
            onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }


            //返回一个新promise对象
            return new Promise((resolve, reject) => {

                //封装一个函数用于处理then返回的值
                function handle(callback) {
                    try {
                        // 先将then方法里面的成功和失败的值次存起来
                        const result = callback(self.data)
                        //情况1:返回新的promise ==> 两种状态
                        // 先判断是不是一个promise对象
                        if (result instanceof Promise) {
                            //如果是用then方法获取成功和失败的值
                            result.then(
                                value => resolve(value),
                                reason => reject(reason)
                            )
                        } else {
                            //情况2:返回的是一个非promise对象 => 将变为成功状态
                            resolve(value)
                        }
                    } catch (error) {
                        // 情况3:抛出错误
                        reject(error)
                    }
                }

                //如果promise是成功状态,异步执行onResolved
                if(self.state === FULFILLED){
                    setTimeout(() => {
                        handle(onResolved)
                    }, 0);
                }else if(self.state === REJECTED){
                //如果promise是失败状态,异步执行onRejected
                    setTimeout(() => {
                        handle(onRejected)
                    }, 0);
                }else{
                    //如果promise是pending默认状态,保存onResolved和Rejected,等状态变成成功或失败时执行
                    self.callbacks.push({
                        resolved : ()=>handle(onResolved),
                        rejected : ()=> handle(onRecjected)
                    })
                }
            })
        }





    window.Promise = Promise
}) (window)
